﻿//========================================================= 
/**@file TC_FingerCmdDriver.h
 * @brief 天诚指纹仪驱动
 * 
 * @date 2017-02-21   17:58:24
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_TC_FINGERCMDDRIVER_H_
#define _LIBZHOUYB_TC_FINGERCMDDRIVER_H_
//--------------------------------------------------------- 
#include "../CommonCmdDriver.h"

#include "../../finger/TC_FingerDevAdapter.h"
using zhou_yb::application::finger::TC_FingerDevAdapter;
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace driver {
//--------------------------------------------------------- 
// 天诚指纹仪驱动
class TC_FingerCmdDriver : 
    public CommonCmdDriver,
    public BaseDevAdapterBehavior<IInteractiveTrans>,
    public InterruptBehavior
{
protected:
    TC_FingerDevAdapter _tcAdapter;
    /// 返回错误码是否为未按手指
    inline bool _IsCaptureFinger() const
    {
        return _tcAdapter.GetAck() == TC_FingerDevAdapter::TCR_NOFP;
    }
public:
    TC_FingerCmdDriver() : CommonCmdDriver()
    {
        _errGetter.Add(_tcAdapter);
        _logSetter.select(_tcAdapter);

        _RegisteAdapterCMD(TC_FingerCmdDriver);
        _RegisteCMD(TC_FingerCmdDriver, GetVersion);
        _RegisteCMD(TC_FingerCmdDriver, IsCaptureFinger);
        _RegisteCMD(TC_FingerCmdDriver, GetFeature);
        _RegisteCMD(TC_FingerCmdDriver, GetTemplate);
        _RegisteCMD(TC_FingerCmdDriver, GetImage);

        _RegisteCancelCMD(TC_FingerCmdDriver);
    }
    LC_CMD_ADAPTER_INVOKE(IInteractiveTrans, _tcAdapter);
    LC_CMD_CANCEL(*this);
    /**
     * @brief 获取版本
     * @date 2017-07-16 13:51
     * 
     * @param IsHex : bool [default:false] 是否直接以16进制格式的字符串导出
     *
     * @retval Version : hex 获取到的版本信息
     */
    LC_CMD_METHOD(GetVersion)
    {
        ByteBuilder version(8);
        if(!_tcAdapter.GetVersion(version))
            return false;
        bool isHex = arg["IsHex"].To<bool>(false);
        ByteConvert::ToString(isHex, version);
        rlt.Put("Version", version.GetString());
        return true;
    }
    /// 是否捕获过指纹
    LC_CMD_METHOD(IsCaptureFinger)
    {
        return _tcAdapter.IsCaptureFinger();
    }
    /**
     * @brief 获取特征
     * @date 2017-02-21 20:32
     *
     * @param [in] Timeout : uint [default:DEV_WAIT_TIMEOUT] 等待按手指的超时时间(ms)
     * @param [in] Interval : uint [default:DEV_OPERATOR_INTERVAL] 等待按手指的轮询间隔(ms)
     * 
     * @retval Data : hex 获取到的特征数据
     */
    LC_CMD_METHOD(GetFeature)
    {
        uint timeoutMs = arg["Timeout"].To<uint>(DEV_WAIT_TIMEOUT);
        uint intervalMs = arg["Interval"].To<uint>(DEV_OPERATOR_INTERVAL);

        ByteBuilder data(8);
        Timer timer;
        while(timer.Elapsed() < timeoutMs)
        {
            if(InterruptBehavior::Implement(*this))
            {
                ResetErr();
                _logErr(DeviceError::OperatorInterruptErr);
                return false;
            }
            if(!_tcAdapter.IsCaptureFinger())
            {
                Timer::Wait(intervalMs);
                continue;
            }
            if(_tcAdapter.GetFeature(data, 0x02))
            {
                rlt.Put("Data", ArgConvert::ToString(data));
                return true;
            }
            if(!_IsCaptureFinger())
                return false;            
            Timer::Wait(intervalMs);
        }
        _logErr(DeviceError::WaitTimeOutErr, "等待放手指超时");
        return false;
    }
    /**
     * @brief 获取模板
     * @date 2017-02-21 20:32
     *
     * @param [in] Timeout : uint [default:DEV_WAIT_TIMEOUT] 等待按手指的超时时间(ms)
     * @param [in] Interval : uint [default:DEV_OPERATOR_INTERVAL] 等待按手指的轮询间隔(ms)
     * 
     * @retval Data : hex 获取到的模板数据
     */
    LC_CMD_METHOD(GetTemplate)
    {
        uint timeoutMs = arg["Timeout"].To<uint>(DEV_WAIT_TIMEOUT);
        uint intervalMs = arg["Interval"].To<uint>(DEV_OPERATOR_INTERVAL);

        ByteBuilder data(8);
        Timer timer;
        while(timer.Elapsed() < timeoutMs)
        {
            if(InterruptBehavior::Implement(*this))
            {
                ResetErr();
                _logErr(DeviceError::OperatorInterruptErr);
                return false;
            }
            if(!_tcAdapter.IsCaptureFinger())
            {
                Timer::Wait(intervalMs);
                continue;
            }
            if(_tcAdapter.GetTemplate(data))
            {
                rlt.Put("Data", ArgConvert::ToString(data));
                return true;
            }
            if(!_IsCaptureFinger())
                return false;
            Timer::Wait(intervalMs);
        }
        _logErr(DeviceError::WaitTimeOutErr, "等待放手指超时");
        return false;
    }
    /**
     * @brief 获取指纹图片
     * @date 2017-04-22 16:33
     * 
     * @param [in] Timeout : uint [default:DEV_WAIT_TIMEOUT] 等待按手指的超时时间(ms)
     * @param [in] Interval : uint [default:DEV_OPERATOR_INTERVAL] 等待按手指的轮询间隔(ms)
     * @param [in] Bmpfile : string 需要保存的指纹图片路径(bmp格式)
     * @param [in] BmpFMT : byte [default:0x0B] 需要保存的BMP格式
     * - 格式:
     *  - 0x00 不返回图像
     *  - 0x01 原始灰度图
     *  - 0x0B 原大灰度
     *  - 0x0C 四分之一灰度
     *  - 0x0D 灰度图二值化
     *  - 0x0E 四分之一灰度图二值化
     * .
     * 
     * @retval Path : string 最后生成的图片路径
     */
    LC_CMD_METHOD(GetImage)
    {
        uint timeoutMs = arg["Timeout"].To<uint>(DEV_WAIT_TIMEOUT);
        uint intervalMs = arg["Interval"].To<uint>(DEV_OPERATOR_INTERVAL);
        string path = arg["Bmpfile"].To<string>();
        byte fmt = arg["BmpFMT"].To<byte>(0x0B);

        ByteBuilder image(35000);
        Timer timer;
        while(timer.Elapsed() < timeoutMs)
        {
            if(_tcAdapter.GetImage(image, fmt))
            {
                if(!TC_FingerDevAdapter::ToBmp(image, path.c_str()))
                {
                    _logErr(DeviceError::OperatorErr, "保存指纹图片失败");
                    return false;
                }
                rlt.Put("Bmpfile", path);
                return true;
            }
            if(!_IsCaptureFinger())
                return false;
            Timer::Wait(intervalMs);
        }
        _logErr(DeviceError::WaitTimeOutErr, "等待放手指超时");
        return false;
    }
};
//--------------------------------------------------------- 
} // nemespace driver
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_TC_FINGERCMDDRIVER_H_
//========================================================= 